import com.alibaba.fastjson.JSONObject;

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.Comparator.comparing;
import static java.util.Comparator.comparingInt;

/**
 * @Description
 * @Author zjj
 * @Date 2021/8/13
 */
public class Lambdatest {
    public static void main(String[] args) {
        Lambdatest.test8();
    }

    public static List<Apple> list = new ArrayList<Apple>() {
        {
            add(new Apple("中国", 3));
            add(new Apple("中国", 2));
            add(new Apple("中国", 4));
            add(new Apple("美国", 4));
            add(new Apple("日本", 3));
            add(new Apple("中国", 2));
            add(new Apple("中国", 7));
            add(new Apple("中国", 6));
            add(new Apple("美国", 1));
            add(new Apple("日本", 7));
            add(new Apple("中国", 1));
            add(new Apple("中国", 4));
            add(new Apple("中国", 10));
            add(new Apple("印度", 4));
            add(new Apple("印度", 3));
        }
    };

    public static void process(Runnable r) {
        System.out.println("===process==");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        r.run();
    }

    public static void test1() {
        int a = 10;
        Runnable r = () -> System.out.println(a);
        System.out.println(a);
        Thread t = new Thread(r);
        t.start();
    }

    /**
     * 比较器
     */
    public static void test2() {
        list.sort(comparing(Apple::getWeight));
        System.out.println(JSONObject.toJSONString(list));
    }

    /**
     * 复合比较器
     */
    public static void test3() {
        //递减
        //重量相同时按照国家排序
        list.sort(comparing(Apple::getWeight).reversed().thenComparing(Apple::getCountry));
        System.out.println(JSONObject.toJSONString(list));
    }

    /**
     * 复合比较器
     */
    public static void test4() {
        Predicate<Apple> predicate1 = (Apple a) -> a.getCountry().equals("中国");
        List<Apple> list1 = list.stream().filter(predicate1).collect(Collectors.toList());
        System.out.println(JSONObject.toJSONString(list1));

        //取非
        Predicate<Apple> predicate2 = predicate1.negate();
        List<Apple> list2 = list.stream().filter(predicate2).collect(Collectors.toList());
        System.out.println("取非:" + JSONObject.toJSONString(list2));

        //and
        Predicate<Apple> predicate3 = predicate1.and(a -> a.getWeight() == 3);
        List<Apple> list3 = list.stream().filter(predicate3).collect(Collectors.toList());
        System.out.println("and:" + JSONObject.toJSONString(list3));

        //or
        Predicate<Apple> predicate4 = predicate1.or(a -> a.getWeight() == 3);
        List<Apple> list4 = list.stream().filter(predicate4).collect(Collectors.toList());
        System.out.println("or:" + JSONObject.toJSONString(list4));
    }

    /**
     * 从文件获得流
     */
    public static void test5() {
        long count = 0;
        try (Stream<String> lines = Files.lines(Paths.get("/Users/zhangjunjie/Desktop/test.txt"), Charset.defaultCharset())) {
            count = lines.flatMap(line -> Arrays.stream(line.split(" "))).distinct().count();
            System.out.println(count);
        } catch (Exception e) {
        }
    }

    /**
     * 创建无限流
     * 迭代：斐波那契数列
     * 生成：
     */
    public static void test6() {
        //迭代
        System.out.println("（迭代）斐波那契数列：");
        Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]}).limit(10).map(t -> t[0]).forEach(System.out::println);

        System.out.println("（生成）随机数：");
        Stream.generate(Math::random).limit(5).forEach(System.out::println);
    }

    /**
     * 规约
     * 连接字符串
     * 连接字符串
     * 求和
     */
    public static void test7() {
        IntSummaryStatistics summarizingInt = list.stream().collect(Collectors.summarizingInt(Apple::getWeight));
        System.out.println("统计方法summarizingInt：" + JSONObject.toJSONString(summarizingInt));
        String collect = list.stream().map(Apple::getCountry).collect(Collectors.joining(",", "(", ")"));
        System.out.println("连接字符串joining：" + collect);
        int total = list.stream().collect(Collectors.reducing(0, Apple::getWeight, Integer::sum));
        System.out.println("求和total：" + total);
    }

    /**
     * 分组
     * 二级分组
     * 分组统计个数
     * 分组统计每个分组最大值
     * groupingBy(根据什么分组，收集器，转换函数)
     */
    public static void test8() {
        Map<Integer, List<Apple>> collect = list.stream().collect(Collectors.groupingBy(Apple::getWeight));
        System.out.println("分组：" + JSONObject.toJSONString(collect));

        Map<String, Long> collect1 = list.stream().collect(Collectors.groupingBy(Apple::getCountry, Collectors.counting()));
        System.out.println("分组统计个数：" + JSONObject.toJSONString(collect1));

        Map<Integer, Map<String, List<Apple>>> collect2 = list.stream().collect(Collectors.groupingBy(Apple::getWeight, Collectors.groupingBy(Apple::getCountry)));
        System.out.println("二级分组：" + JSONObject.toJSONString(collect2));


        Map<String, Optional<Apple>> collect3 = list.stream().collect(Collectors.groupingBy(Apple::getCountry, Collectors.maxBy(comparingInt(Apple::getWeight))));
        System.out.println("分组统计每个分组最大值(Optional<Apple>)：" + JSONObject.toJSONString(collect3));

        Map<String, Apple> collect4 = list.stream().collect(Collectors.groupingBy(Apple::getCountry, Collectors.collectingAndThen(Collectors.maxBy(comparingInt(Apple::getWeight)), Optional::get)));
        System.out.println("分组统计每个分组最大值（转换类型Optional<Apple> =>Apple）：" + JSONObject.toJSONString(collect4));

        Map<String, Integer> collect5 = list.stream().collect(Collectors.groupingBy(Apple::getCountry, Collectors.summingInt(Apple::getWeight)));
        System.out.println("分组统计每个分组和：" + JSONObject.toJSONString(collect5));

        Map<String, Set<Integer>> collect6 = list.stream().collect(Collectors.groupingBy(Apple::getCountry, Collectors.mapping(m -> m.getWeight(), Collectors.toSet())));
        System.out.println("分组统计每个分组再结合其他的收集器mapping：：" + JSONObject.toJSONString(collect6));

        Map<String, Set<Integer>> collect7 = list.stream().collect(Collectors.groupingBy(Apple::getCountry, Collectors.mapping(m -> m.getWeight(), Collectors.toCollection(HashSet::new))));
        System.out.println("分组统计每个分组再结合其他的收集器mapping(自定义collection)：：" + JSONObject.toJSONString(collect7));

        Map<Boolean, List<Apple>> collect8 = list.stream().collect(Collectors.partitioningBy(m -> m.getCountry().equals("中国")));
        System.out.println("分区：" + JSONObject.toJSONString(collect8));

        Map<Boolean, Map<Integer, List<Apple>>> collect9 = list.stream().collect(Collectors.partitioningBy(m -> m.getCountry().equals("中国"), Collectors.groupingBy(Apple::getWeight)));
        System.out.println("分区后再分组：" + JSONObject.toJSONString(collect9));

        Map<Boolean, Apple> collect10 = list.stream().collect(Collectors.partitioningBy(m -> m.getCountry().equals("中国"), Collectors.collectingAndThen(Collectors.maxBy(comparingInt(Apple::getWeight)), Optional::get)));
        System.out.println("分区后再针对分区统计最大值：" + JSONObject.toJSONString(collect10));

        Map<String, Apple> collect11 = list.stream().collect(Collectors.toMap(Apple::getCountry, Function.identity(), (v1, v2) -> v1));
        System.out.println("toMap：" + JSONObject.toJSONString(collect11));
    }

    /**
     * 自定义收集器但不去实现Collector
     */
    public static void test9() {
        ArrayList<Object> collect = list.stream().collect(ArrayList::new, List::add, List::addAll);
        System.out.println("自定义收集器：：" + JSONObject.toJSONString(collect));
    }

    public static void test10() {
        Optional<Apple> optionalApple = Optional.empty();
        Apple apple = optionalApple.orElseGet(() -> {
            try {
                Thread.sleep(1000);
                System.out.println(111);
                return new Apple("aa", 12);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return new Apple("aa", 12);
        });
        System.out.println(1);
    }

}
